P12-1. 카오스 엔지니어링과 근본 원인 분리 종합 실습 - 이론 개념

P12-1. 카오스 엔지니어링과 근본 원인 분리 종합 실습 - 이론 개념

학습 목표

  1. **카오스 엔지니어링(Chaos Engineering)**의 핵심 철학과 정상 상태 가설(Steady-State Hypothesis) 기반 실험 설계 원리를 이해한다.
  2. 실무 장애 대응에서 가장 빈번하게 논쟁이 벌어지는 **"네트워크/메시 계층 지연(L7 Fault Delay)"**과 **"데이터베이스 락 경합 지연(PostgreSQL Row-Level Lock Contention)"**의 메커니즘 차이를 구조적으로 파악한다.
  3. **Istio Ambient Mesh(ztunnel + waypoint)**와 **LGTM 스택(VictoriaMetrics · Loki · Tempo · Grafana · Kiali · postgres-exporter)**의 시그널을 교차 대조하여 단 1분 만에 근본 원인을 분리하는 RCA(Root Cause Analysis) 의사결정 트리를 마스터한다.


1. 카오스 엔지니어링(Chaos Engineering)의 본질

1.1 왜 고의로 장애를 주입하는가?

마이크로서비스와 하이브리드 클라우드(Kubernetes + 외부 VM DB) 아키텍처에서는 모든 컴포넌트가 정상일 때만 테스트해서는 실전 장애를 막을 수 없다.

용어 정리: 카오스 엔지니어링 (Chaos Engineering) & 정상 상태 가설 (Steady-State Hypothesis)

  • 카오스 엔지니어링 (Chaos Engineering): 분산 시스템이 프로덕션 환경의 예측 불가능한 장애 상황을 견딜 수 있는지 확인하기 위해, 통제된 환경에서 의도적으로 장애(지연, 에러, 락 경합 등)를 주입하고 시스템의 반응과 관측 가능성(Observability)을 검증하는 공학적 실험 기법이다.
  • 정상 상태 가설 (Steady-State Hypothesis): 실험 전 시스템이 정상적으로 동작하고 있음을 나타내는 정량적 기준선(예: HTTP 200 성공률 99.9%, P99 응답 시간 < 50ms, pg_locks 대기 세션 0개)이다.
  • 폭발 반경 (Blast Radius): 주입한 장애가 영향을 미치는 범위다. Istio VirtualService의 URI/헤더 매칭이나 특정 DB 행(WHERE id = 1)만 타겟팅하면 전체 서비스를 멈추지 않고 폭발 반경을 좁혀 안전하게 실험할 수 있다.


2. 실무 최대 난제: "네트워크가 느린가, DB가 느린가?"

클라이언트 입장에서는 네트워크/메시 구간에서 3초가 지연되든, 데이터베이스에서 Row Lock 때문에 5초가 지연되든 똑같이 **"API 응답이 수 초 동안 멈췄다"**고 느낀다. 관측 파이프라인이 없다면 네트워크/인프라 엔지니어와 백엔드/DBA 사이에 끝없는 책임 공방(Blame Game)이 벌어진다.

우리가 Part 01부터 Part 11까지 구축한 Ambient Mesh + LGTM + PostgreSQL 관측 파이프라인은 이 두 가지 장애를 전혀 다른 **지문(Fingerprint)**으로 즉시 구별해 낸다.

flowchart TB
    subgraph ClientSide["클라이언트 체감 증상 (동일)"]
        Symptom["API 응답 지연 발생 (3초 ~ 6초)"]
    end

    Symptom --> Check1{"1단계: Waypoint Access Log & Tempo Span 확인"}

    Check1 -->|"DURATION=3005ms
UPSTREAM_SERVICE_TIME=3ms
RESPONSE_FLAGS=DI"| RootA["원인 A: 네트워크 / 메시 L7 계층 지연
(애플리케이션 및 DB는 3ms 만에 정상 처리)"] Check1 -->|"DURATION=5000ms+
RESPONSE_FLAGS=-
(또는 PG TCP 세션 장시간 유지)"| Check2{"2단계: VictoriaMetrics & PostgreSQL 뷰 확인"} Check2 -->|"pg_locks_count 상승
wait_event_type='Lock'
pg_blocking_pids() 존재"| RootB["원인 B: PostgreSQL Row-Level Lock 경합
(선행 미커밋 트랜잭션이 행 잠금 점유)"] Check2 -->|"pg_locks 정상 (대기 없음)
wait_event_type='IO' / 'CPU'
pg_stat_statements mean_exec_time 급증"| RootC["원인 C: 비효율적 SQL 쿼리 / 인덱스 누락
(Full Table Scan 또는 디스크 I/O 병목)"]

3. 시나리오별 관측 지문(Observability Fingerprint) 상세 비교

3.1 시나리오 A: 네트워크/메시 계층 지연 (Istio L7 Fault Delay)

Istio VirtualService를 통해 order-api의 /chaos-net 경로에 fixedDelay: 3s를 주입했을 때 각 계층에 남는 증거는 다음과 같다.

  1. Loki (Waypoint Envoy Access Log):
    • %DURATION% (전체 소요 시간): 3005 ms
    • %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% (실제 백엔드 파드가 처리한 시간): 3 ms
    • %RESPONSE_FLAGS%: DI (Delay Injected)
    • 결론: 3005ms - 3ms = 3002ms가 백엔드 컨테이너 밖(프록시/네트워크 계층)에서 소비되었으며, 백엔드 애플리케이션은 단 3ms 만에 응답을 마쳤다!
  2. Tempo (분산 추적 Span):
    • Span의 총 길이는 3.01s이지만, Span Attribute에 response_flags = "DI"가 명시되어 있다.
  3. VictoriaMetrics & PostgreSQL (postgres-exporter):
    • pg_stat_activity에 대기 중인 쿼리가 0건이며, pg_locks_count 변화도 전혀 없다.

3.2 시나리오 B: 데이터베이스 행 잠금 경합 (PostgreSQL Row-Level Lock Contention)

외부 VM 데이터베이스(pg-vm.mesh.internal, ordersdb)에서 선행 세션(Session 1)이 SELECT ... FOR UPDATE로 id = 1 행을 잠근 채 커밋하지 않고 있을 때, 후행 세션(Session 2)이 같은 행에 UPDATE를 시도하는 상황이다.

  1. Loki (Waypoint TCP Access Log):
    • inbound-vip|5432|tcp|pg-vm.mesh.internal 로그의 %DURATION%(세션 유지 시간)이 5,000ms ~ 7,000ms 이상으로 길어진다.
    • %RESPONSE_FLAGS%는 -(정상 TCP 스트림)이다. 즉, 네트워크 단절이나 프록시 지연 주입이 아님을 증명한다.
  2. VictoriaMetrics (postgres-exporter 메트릭):
    • pg_locks_count{datname="ordersdb", mode="exclusivelock"} 및 rowexclusivelock 수치가 상승한다.
    • pg_stat_activity_count{datname="ordersdb", state="active"} 및 idle in transaction 세션이 동시에 관측된다.
  3. PostgreSQL 내부 뷰 (pg_stat_activity & pg_stat_statements):
    • pg_stat_activity에서 지연 중인 세션의 wait_event_type = 'Lock', wait_event = 'transactionid'가 선명하게 포착되며, pg_blocking_pids(pid) 함수가 범인 세션의 PID를 정확히 지목한다.
    • 트랜잭션이 끝난 직후 pg_stat_statements를 조회하면 해당 UPDATE 구문의 mean_exec_time(또는 max_exec_time)이 수천 ms로 기록된다.

4. 두 시나리오의 핵심 지표 비교 요약표

관측 계층 및 지표 시나리오 A: 네트워크/메시 지연 (3s) 시나리오 B: PostgreSQL Row Lock 경합 (6s)
클라이언트 체감 응답 시간 약 3.0 ~ 3.3초 (지연) 약 5.0 ~ 6.0초 (지연)
Waypoint %DURATION% 3005 ms TCP 세션 5000 ~ 7000 ms
Waypoint upstream_service_time 3 ms (백엔드는 즉시 응답!) - (TCP) 또는 백엔드 대기 시간 그대로 증가
Envoy %RESPONSE_FLAGS% DI (Delay Injected) - (네트워크/프록시 이상 없음)
Tempo Span 속성 response_flags: "DI" DB 호출 구간 Span 길이 증가
PG wait_event_type / wait_event 없음 (idle) Lock / transactionid
PG pg_blocking_pids(pid) {} (빈 배열) {선행_세션_PID} (블로커 즉시 특정)
PG pg_stat_statements 실행 시간 변화 없음 (< 1ms) UPDATE 쿼리 실행 시간 5000ms+ 폭증

5. 종합 아키텍처 회고: Part 00 ~ Part 12 전체 여정

이로써 우리는 단일 클러스터와 외부 VM을 아우르는 엔터프라이즈급 Service Mesh & Observability 풀스택 아키텍처를 바닥부터 직접 설계하고 검증했다.

  1. 인프라 & 데이터플레인 (Part 00 ~ Part 05):
    • 3노드 Kubernetes 클러스터 위에 사이드카 없는 **Istio Ambient Mesh (ztunnel L4 + waypoint L7)**를 구축하고, HBONE(:15008) mTLS 암호화, SPIFFE ID 기반 Zero-Trust 인가, 카나리 라우팅, 서킷 브레이커를 완성했다.
  2. 하이브리드 VM 확장 & DB 아키텍처 (Part 06 ~ Part 07):
    • 클러스터 외부의 **PostgreSQL 18 VM(study-pg-vm)**을 ServiceEntry · WorkloadEntry로 메시에 편입시키고, MVCC 튜플 구조(ctid), Vacuum, Row Lock, Terraform IaC 설계를 검증했다.
  3. LGTM 통합 관측성 & 카오스 검증 (Part 08 ~ Part 12):
    • 차세대 통합 수집기 Grafana Alloy를 중심으로 VictoriaMetrics(Metrics) · Loki(Logs) · Tempo(Traces) · Grafana · Kiali를 연결하여, 어떠한 복합 장애가 발생하더라도 **데이터에 기반해 1분 안에 근본 원인을 분리(RCA)**할 수 있는 관측 체계를 완성했다.

네비게이션

이전 목록 다음
◀ Part 11 실습 목록으로 Part 12 실습 ▶